/*
* Copyright (C) 2019 ~ 2022 Uniontech Software Technology Co.,Ltd.
*
* Author:     yanghongwei <yanghongwei@uniontech.com>
*
* Maintainer: yanghongwei <yanghongwei@uniontech.com>
*/

#include "filenotify.h"
#include "inotify.h"
#include "fanotify.h"
#include "abstractnotify.h"
#include "abstractnotifyprocess.h"

#include <functional>

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;

FileNotify::FileNotify()
    : m_isInit(false)
{
    // 创建inotify和fanotify
    m_allNotify[I_Notify] = new INotify();
    m_allNotify[Fa_Notify] = new FaNotify();
}

FileNotify::~FileNotify()
{
    // TODO: inotify和fanotify还未做释放处理
}

/**
 * @brief 获取单例
 * @return 返回FileNotify对象
 */
FileNotify *FileNotify::instance()
{
    static FileNotify *instance = new FileNotify();
    return instance;
}

/**
 * @brief 初始化inotify和fanotify
 * @return true:初始化成功 false:初始化失败
 */
bool FileNotify::init()
{
    // 已经初始化
    if (m_isInit) {
        return true;
    }
    // 初始化inotify
    if (!m_allNotify[I_Notify]->init()) {
        return false;
    }
    // 初始化fanotify
    m_isInit = m_allNotify[Fa_Notify]->init();
    return m_isInit;
}

/**
 * @brief 添加一个要监听的节点
 * @param node 监听节点
 * @param notifyType 事件通知类型
 * @return true:添加成功 false:添加失败
 */
bool FileNotify::addNode(const NotifyNode &node, NotifyType notifyType)
{
    switch (notifyType) {
    case I_Notify:
    case Fa_Notify:
        // 添加监听
        if (!m_allNotify[notifyType]->addNode(node)) {
            return false;
        }
        // 监听成功，缓存监听节点
        m_allNode[notifyType].push_back(node);
        // 如果线程为启动，则启动线程
        if (!m_allNotify[notifyType]->isRunning()) {
            m_allNotify[notifyType]->start();
        }
        break;
    default:
        return false;
    }

    return true;
}

/**
 * @brief 移除一个已经监听的节点
 * @param node 监听节点
 * @param notifyType 事件通知类型
 * @return true:移除成功 false:移除失败
 */
bool FileNotify::removeNode(const NotifyNode &node, NotifyType notifyType)
{
    switch (notifyType) {
    case I_Notify:
    case Fa_Notify:
        m_allNotify[notifyType]->removeNode(node);
        break;
    default:
        return false;
    }

    return true;
}

/**
 * @brief 添加一个业务处理对象
 * @param process 业务处理对象
 * @return true:添加成功 false:添加失败
 */
bool FileNotify::addProcess(AbstractNotifyProcess *process)
{
    switch (process->notifyType) {
    case I_Notify:
    case Fa_Notify:
        m_allNotify[process->notifyType]->setNotifyCbFun(std::bind(&AbstractNotifyProcess::notifyCallBackFun, process, _1, _2, _3, _4), process);
        break;
    default:
        return false;
    }
    return true;
}

/**
 * @brief 移除一个业务处理对象
 * @param process 业务处理对象
 * @return true:移除成功 false:移除失败
 */
bool FileNotify::removeProcess(AbstractNotifyProcess *process)
{
    switch (process->notifyType) {
    case I_Notify:
    case Fa_Notify:
        m_allNotify[process->notifyType]->unSetNotifyCbFun(process);
        break;
    default:
        return false;
    }
    return true;
}
